/*---------------------------------------------------------------------------
	ZaRan	-	A Totallly Automatic CFD Software
	Copyright (C) ,Since 2020
-------------------------------------------------------------------------------
License
	This file is part of ZaRan.

!	@file		gird.h
!	@brief	the purpose of this file.
!	@author	Chen Jie.
\*---------------------------------------------------------------------------*/
#include"model/include/pointcloud.h"
#include"Basic/include/CommonPara.h"
ModPointCloud::ModPointCloud(vector<Point>& point_list)
{
	pointVec coord_list;
	point_t coord;
	Point max, min;
	max = Point(-LARGE_NUMBER, -LARGE_NUMBER, -LARGE_NUMBER);
	min = Point(LARGE_NUMBER, LARGE_NUMBER, LARGE_NUMBER);
	coord_list.resize(point_list.size());
	for (size_t iPoint = 0; iPoint < point_list.size(); ++iPoint)
	{
		coord = { point_list[iPoint].x(), point_list[iPoint].y(), point_list[iPoint].z() };
		max.ChangeCoord(std::max(max.x(), coord[0]), std::max(max.y(), coord[1]), std::max(max.z(), coord[2]));
		min.ChangeCoord(std::min(min.x(), coord[0]), std::min(min.y(), coord[1]), std::min(min.z(), coord[2]));
		coord_list[iPoint] = coord;
	}
	this->SetBoxMax(max);
	this->SetBoxMin(min);
	point_cloud_ = KDTree(coord_list);
}

bool ModPointCloud::IsInModel(const Point& pt)
{
	double near_dist = 2e-2;
	if (this->GetBoxMin().x() - pt.x() > near_dist || pt.x() - this->GetBoxMax().x() > near_dist)
		return false;
	if (this->GetBoxMin().y() - pt.y() > near_dist || pt.y() - this->GetBoxMax().y() > near_dist)
		return false;
	if (this->GetBoxMin().z() - pt.z() > near_dist || pt.z() - this->GetBoxMax().z() > near_dist)
		return false;
	if (NearestDistance(pt) < near_dist)
		return true;
	else
		return false;
}

void ModPointCloud::GenModelPoint(const double delta)
{
	// Model is construct by point cloud
	// do nothing!
}
Point ModPointCloud::GetClosestPoint(const Point& pt)
{
	point_t coord = { pt.x(),pt.y(),pt.z() };
	point_t nearest_coord = point_cloud_.nearest_point(coord);
	return Point(nearest_coord[0], nearest_coord[1], nearest_coord[2]);
}
double ModPointCloud::NearestDistance(const Point& pt)
{
	Point near_point = GetClosestPoint(pt);
	return distance(pt, near_point);
}
